<template>
  <div id="all">
    <div id="">
      <h2 title="模仿测试数据 dev环境 工作空间 YXH_TEST_02 任务名称 test1019">
        cytoscape demo
      </h2>
      <h3>
        参考文献地址：
        <el-link
          @click="
            open(
              'https://blog.csdn.net/dahaiaixiaohai/article/details/89669526'
            )
          "
          type="primary"
        >
          https://blog.csdn.net/dahaiaixiaohai/article/details/89669526
        </el-link>
      </h3>
      <h3 @click="open('https://js.cytoscape.org/')">
        官方文档:
        <el-link type="primary">https://js.cytoscape.org/</el-link>
      </h3>
      <h3>cytoscape 设置面板</h3>
      <div id="">
        <span id="">缩放图形</span>
        <el-switch
          v-model="zooming"
          active-color="#13ce66"
          inactive-color="#ff4949"
        ></el-switch>
        <span id="" class="mgL20">拖拽节点</span>
        <el-switch
          v-model="autoungrabify"
          active-color="#13ce66"
          inactive-color="#ff4949"
        ></el-switch>
        <span id="" class="mgL20">平移画布</span>
        <el-switch
          v-model="panning"
          active-color="#13ce66"
          inactive-color="#ff4949"
        ></el-switch>
        <span id="" class="mgL20">图形背景</span>
        <el-switch
          v-model="imageFlag"
          active-color="#13ce66"
          inactive-color="#ff4949"
        ></el-switch>
        <span id="" v-if="!imageFlag" class="mgL20">节点颜色</span>
        <el-color-picker
          v-if="!imageFlag"
          v-model="color"
          size="mini"
        ></el-color-picker>
        <span id="" class="mgL20">自适应视口</span>
        <el-switch
          v-model="fit"
          active-color="#13ce66"
          inactive-color="#ff4949"
        ></el-switch>
        <span class="mgL20">节点形状</span>
        <el-select v-model="typeValue" placeholder="请选择"
          ><el-option
            v-for="item in typeList"
            :key="item"
            :label="item"
            :value="item"
          ></el-option
        ></el-select>
        <el-button
          size="small"
          class="mgL20 btn"
          type="primary"
          icon="el-icon-refresh"
          @click="refresh"
        ></el-button>
        <el-button size="small" class="mgL20 btn" type="primary" id="inner"
          >嵌入名字模式</el-button
        >
      </div>
    </div>
    <div id="nodeHead" class="flex">
      <span id="nodeHeadText">
        <i
          class="el-icon-warning-outline"
          style="color: #edda0e; font-size: 18px"
        ></i>
        鼠标右键节点可显示菜单
      </span>
      <span class="mgL30 flex">
        节点状态:
        <span class="mgL20 flex">
          <img class="" id="p309801" src="../../assets/p309801.png" />
          运行成功
        </span>
        <span class="mgL20 flex">
          <img class="mgL10" src="../../assets/p309802.png" />
          未运行
        </span>
        <span class="mgL20 flex">
          <img class="mgL10" src="../../assets/p309803.png" />
          运行失败
        </span>
        <span class="mgL20 flex">
          <img class="mgL10" src="../../assets/p309804.png" />
          正在运行
        </span>
        <span class="mgL20 flex">
          <img class="mgL10" src="../../assets/p309805.png" />
          等待
        </span>
        <span class="mgL20 flex">
          <img class="mgL10" src="../../assets/p309806.png" />
          暂停/冻结
        </span>
      </span>
    </div>
    <div id="box" @contextmenu.prevent.stop="nodeContextmenu">
      <div id="innerSrc" v-show="innerFlag">
        <img src="../../assets/p309801.png" />
      </div>
      <div id="menu" data-title="右键菜单" v-show="menuFlag">
        <div @click.stop="selectMenu($event)">菜单一</div>
        <div @click.stop="selectMenu($event)">菜单二</div>
        <div @click.stop="selectMenu($event)">菜单三</div>
      </div>
      <div id="cy" data-title="图"></div>

      <div id="info" v-show="infoFlag" data-title="详情内容">
        <div class="title">
          <span class="nodeInfoTitle">节点名称：</span>
          <span class="nodeInfoText">{{ Node.name }}</span>
        </div>
        <div>
          <span id="nodeId" class="nodeInfoTitle">节点ID：</span>
          <span class="nodeInfoText">{{ Node.id }}</span>
        </div>
        <div>
          <span class="nodeInfoTitle">任务名称：</span>
          <span class="nodeInfoText">test_task_0712</span>
        </div>
        <div>
          <span class="nodeInfoTitle">实例状态：</span>
          <span class="nodeInfoText">失败</span>
        </div>
        <div>
          <span class="nodeInfoTitle">开始时间：</span>
          <span class="nodeInfoText">2021-10-27 17:42:54</span>
        </div>
        <div>
          <span class="nodeInfoTitle">结束时间：</span>
          <span class="nodeInfoText">2021-10-27 17:42:59</span>
        </div>
        <div>
          <span class="nodeInfoTitle">耗时(秒)：</span>
          <span class="nodeInfoText">5</span>
        </div>
      </div>
      <div>
        <span
          v-show="false"
          class="typeDiv"
          v-for="(item, index) in Nodes"
          :key="index"
          :data-type="item.data.id"
          >{{ item.data.typeClass }}</span
        >
      </div>
    </div>
    <el-drawer
      :title="title"
      :visible.sync="drawer"
      :before-close="handleClose"
    >
      <span>{{ name }}</span>
    </el-drawer>
    <transition name="el-fade-in">
      <div id="rlb" v-show="rlbFlag">
        <!-- <div id="d1">详情</div> -->
        <div id="d2">节点名称：XXXX</div>
        <div style="margin-bottom: 10px">节点ID：XXXX</div>
        <el-skeleton :rows="3" />
      </div>
    </transition>
    <div>
      <span
        v-show="false"
        class="idDiv"
        v-for="(item, index) in Nodes"
        :key="index"
        :data-id="item.data.id"
        >{{ item.data.name }}</span
      >
    </div>
  </div>
</template>

<script>
import $ from "jquery";
import cytoscape from "cytoscape";
import { nodes, edges } from "@/assets/js/cytoscapeData.js";
import { jsonData, jsonData2 } from "@/assets/js/testData.js";
import { logo } from "@/assets/logo.png";
var cy = null;
export default {
  name: "App",
  data() {
    return {
      Node: {}, //节点对象
      menuFlag: false,
      infoFlag: false,
      zooming: false,
      panning: false,
      innerFlag: false,
      Nodes: [],
      i: 0,
      rlbFlag: false,
      name: "",
      title: "",
      drawer: false,
      autoungrabify: false,
      cyObj: {},
      typeValue: "round-rectangle", //形状类型
      color: null,
      typeList: [
        "ellipse",
        "triangle",
        "round-triangle",
        "rectangle",
        "round-rectangle",
        "bottom-round-rectangle",
        "cut-rectangle",
        "barrel",
        "rhomboid",
        "diamond",
        "round-diamond",
        "pentagon",
        "round-pentagon",
        "hexagon",
        "round-hexagon",
        "concave-hexagon",
        "heptagon",
        "round-heptagon",
        "octagon",
        "round-octagon",
        "star",
        "tag",
        "round-tag",
        "vee",
      ], //形状类型容器
      imageFlag: false,
      fit: false,
      downFlag: false,
      layoutObj: {},
      styleObj: {},
    };
  },
  mounted() {
    this.refresh();
    this.Nodes = nodes;
  },
  methods: {
    move() {
      console.log("move");
      return;
    },
    handleClose(done) {
      done();
    },
    open(url) {
      window.open(url);
    },
    jpg() {
      let j = this.cyObj.jpg();
      console.log(j);
      window.open(j);
    },
    nodeContextmenu(eve) {
      //节点右键
      console.log(eve);
      let me = this;

      if (me.Node && me.Node.id) {
        let x = me.Node.x;
        let y = me.Node.y;
        let box = $("#box");
        let h = box.position().top;
        console.log("Node", me.Node);
        $("#menu").prop("style", function (i, val) {
          val.top = me.Node.position.y + me.Node.pan.y + "px";
          val.left = eve.clientX - 10 + "px";
        });
        me.infoFlag = false;
        me.menuFlag = true;
      } else {
        return;
      }
    },
    selectMenu() {
      //选中菜单
      console.log("选中菜单");
      this.menuFlag = false;
    },
    refresh() {
      let me = this;
      me.innerFlag = false;
      if (cy) {
        cy.destroy();
      }
      console.log("refresh cytoscape demo");
      me.$notify({
        title: "Refresh",
        message: "refresh cytoscape demo",
        type: "success",
      });

      if (me.typeValue) {
        nodes.map((item) => {
          item.data.type = me.typeValue;
        });
      }
      me.layoutObj = {
        name: "preset", //该random布局使节点在视口内随机位置。
        fit: me.fit, //如果要适应视区
        padding: 15, //安装padding
        // boundingbox: { x1: '0', y1: '300', w: '300', h: '300' }, //约束布局边界；x1，y1，x2，y2或x1，y1，w，h
        animate: false, //如果要转换节点位置
        animationDuration: 500,
        minNodeSpacing: 180, //控制大小
        maxNodeSpacing: 220, //控制大小
        // 动画持续时间： 500, //如果启用动画持续时间（毫秒）
        // AnimationEleasing: 未定义， //如果启用，则释放动画
        // animatefilter： 函数（ node， i） 返回true；， //一个确定是否应为节点设置动画的函数。默认情况下，所有节点都启用了动画。非动画节点在布局开始时立即定位。
        // ready: '函数', //layoutready上的回调
        // stop: 未定义， //在layoutstop上回调
        // transform： 函数（ node， position） 返回位置； //转换给定的节点位置。用于在离散布局中更改方向
        transform: (node, position) => {
          /* console.log("transform node",node);
						console.log("transform position",position);
						if(node.id() == "start"){
							position= {x:0,y:0}
						} */
          return position;
        },
      };
      me.styleObj = [
        {
          //样式
          selector: "node", //节点样式
          style: {
            shape: "data(type)", //形状
            content: "data(name)", //显示内容
            "text-valign": "top", //文字位置
            "text-halign": "top",

            "background-image": me.imageFlag
              ? () => {
                  let src = $("#p309801").attr("src");
                  return [src];
                }
              : [],
            // 'background-image-containment': ['over', 'inside'],
            // 'background-clip': ['none', 'none'],
            // 'bounds-expansion': 25,
            // 'background-width': [20, 20],
            // 'background-height': [20, 20],
            // 'background-position-x': ['-10','120%'],
            // 'background-position-y': ['-10','-10'],
            "background-color": me.color ? me.color : "#DBEFFF",
            "border-color": "gray",
            "border-width": 1,
            // 'background-image': '../../assets/logo.png',
            "background-fit": "cover",
            // 'background-color':'#66b1ff',
            // 'color':'data(textColor)',
            "text-opacity": 0.8,
            height: 40,
            width: 140,
            "pie-size": "100%",
            "active-bg-color": "red",
            "selection-box-color": "blue",
            // 'pie-1-background-color': '#E8747C',
            // 'pie-1-background-size': 'mapData(occupy, 0, 10, 0, 100)',
          },
        },
        {
          selector: ":parent", //组合
          css: {
            "text-valign": "top",
            "text-halign": "center",
            // 'text-halign': 'right',
            // 'text-rotation': '90deg', //文字旋转
          },
        },
        {
          selector: ".selectNode", //选中样式
          css: {
            "border-color": "#666",
            "border-width": 2,
          },
        },
        {
          selector: ".w", //选中样式
          css: {
            "text-valign": "center",
            "text-halign": "center",
          },
        },
        {
          selector: "edge", //连线样式
          style: {
            width: 5,
            // 'curve-style': 'haystack',
            "curve-style": "bezier",
            label: "data(label)",
            "target-arrow-shape": "triangle",
            // "target-arrow-fill": "hollow", //箭头填充 空心
            color: "data(textColor)",
            cursor: "pointer",
            "line-color": "#9dbaea",
            "target-arrow-color": "#9dbaea",
            "curve-style": "bezier",
          },
        },
      ];
      // autoungrabify: me.autoungrabify, //节点是否可以拖拽
      // userZoomingEnabled: me.zooming, //是否允许用户事件（例如鼠标滚轮，捏合缩放）缩放图形
      cy = cytoscape({
        zoom: 1, // 图表的初始缩放级别.可以设置options.minZoom和options.maxZoom设置缩放级别的限制.
        pan: { x: 0, y: 0 }, // 图表的初始平移位置.
        // interaction options:
        minZoom: 0.3, // 图表缩放级别的最小界限.视口的缩放比例不能小于此缩放级别.
        maxZoom: 1.5, // 图表缩放级别的最大界限.视口的缩放比例不能大于此缩放级别.
        zoomingEnabled: true, // 是否通过用户事件和编程方式启用缩放图形.
        userZoomingEnabled: me.zooming, // 是否允许用户事件(例如鼠标滚轮,捏合缩放)缩放图形.对此缩放的编程更改不受此选项的影响.
        autoungrabify: me.autoungrabify ? false : true, // 默认情况下节点是否不允许被拾取(用户不可抓取,如果true覆盖单个节点状态).
        panningEnabled: me.panning, // 是否通过用户事件和编程方式启用平移图形,画布平移功能.
        userPanningEnabled: true, // 是否允许用户事件(例如拖动图形背景)平移图形.平移的程序化更改不受此选项的影响.
        boxSelectionEnabled: true, // 是否启用了框选择(即拖动框叠加,并将其释放为选择).如果启用,则用户必须点击以平移图表.
        selectionType: "additive", // 一个字符串，指示用户输入的选择行为.对于'additive',用户进行的新选择将添加到当前所选元素的集合中.对于'single',用户做出的新选择成为当前所选元素的整个集合.
        touchTapThreshold: 8, // 非负整数,分别表示用户在轻击手势期间可以在触摸设备和桌面设备上移动的最大允许距离.这使得用户更容易点击.
        // 这些值具有合理的默认值,因此建议不要更改这些选项,除非您有充分的理由这样做.大值几乎肯定会产生不良后果。
        desktopTapThreshold: 4, // 非负整数,分别表示用户在轻击手势期间可以在触摸设备和桌面设备上移动的最大允许距离.这使得用户更容易点击.
        // 这些值具有合理的默认值,因此建议不要更改这些选项,除非您有充分的理由这样做.大值几乎肯定会产生不良后果。
        autolock: true, // 默认情况下是否应锁定节点(根本不可拖动,如果true覆盖单个节点状态).

        autounselectify: true, // 默认情况下节点是否允许被选择(不可变选择状态,如果true覆盖单个元素状态).
        // rendering options:
        headless: false, // true:空运行,不显示不需要容器容纳.false:显示需要容器容纳.
        styleEnabled: true, // 一个布尔值,指示是否应用样式.
        hideEdgesOnViewport: true, // 渲染提示,设置为true在渲染窗口时,不渲染边.例如,移动某个顶点时或缩放时,边信息会被临时隐藏,移动结束后,边信息会被执行一次渲染.由于性能增强,此选项现在基本上没有实际意义.
        hideLabelsOnViewport: false, // 渲染提示,当设置为true使渲染器在平移和缩放期间使用纹理而不是绘制元素时,使大图更具响应性.由于性能增强,此选项现在基本上没有实际意义.
        textureOnViewport: false, // 渲染提示,当设置为true使渲染器在平移和缩放期间使用纹理而不是绘制元素时,使大图更具响应性.由于性能增强,此选项现在基本上没有实际意义.
        motionBlur: false, // 渲染提示,设置为true使渲染器使用运动模糊效果使帧之间的过渡看起来更平滑.这可以增加大图的感知性能.由于性能增强,此选项现在基本上没有实际意义.
        motionBlurOpacity: 0.2, // 当motionBlur:true,此值控制运动模糊帧的不透明度.值越高,运动模糊效果越明显.由于性能增强,此选项现在基本上没有实际意义.
        wheelSensitivity: 0.5, // 缩放时更改滚轮灵敏度.这是一个乘法修饰符.因此,0到1之间的值会降低灵敏度(变焦较慢),而大于1的值会增加灵敏度(变焦更快).
        pixelRatio: "auto", // 使用手动设置值覆盖屏幕像素比率(1.0建议,如果已设置).这可以通过减少需要渲染的有效区域来提高高密度显示器的性能,
        // 尽管在最近的浏览器版本中这是不太必要的.如果要使用硬件的实际像素比,可以设置pixelRatio: 'auto'(默认).
        wheelSensitivity: 0.1, //缩放时更改滚轮灵敏度。
        minZoom: 0.3, //图表缩放得最小界限

        container: document.getElementById("cy"),
        /**
								 * preset 该preset布局使节点在您手动指定的位置。
									grid grid布局使节点在良好隔开的网格。
									circle 该circle布局使节点在一个圆圈。
									concentric 该concentric布局定位在同心圆节点，根据您所指定的节点分隔成水平的度量。此布局设置concentric值ele.scratch()。
									breadthfirst breadthfirst布局使在层次结构中的节点，基于所述图的breadthfirst遍历。默认的自上而下模式
									random, //该random布局使节点在视口内随机位置。
								 */
        layout: me.layoutObj,
        style: me.styleObj,
        elements: {
          //数据对象
          //节点数据
          nodes: nodes,
          //连线数据
          edges: edges,
        },
      });
      // 监听节点的点击事件
      cy.on("tap", "node", function (evt) {
        var node = evt.target;
        let name = node._private.data.name;
        let id = node.id();
        console.log("tapped node", id);
        me.$notify.info({
          title: "消息",
          message: "node id is " + node.id(),
        });
        me.title = "ID:" + node.id();
        me.name = name;
        // me.drawer = true;
        me.rlbFlag = true;
        me.menuFlag = false;
        cy.nodes().classes([]); // 清空所有样式
        // cy.$('#'+id).addClass('selectNode');//选中节点增加样式
        if (me.innerFlag) {
          cy.nodes().addClass("w");
          cy.$("#" + id).addClass("selectNode"); //选中节点增加样式
        } else {
          cy.$("#" + id).addClass("selectNode"); //选中节点增加样式
        }
      });
      //监听鼠标移入节点事件
      cy.on("mouseover ", "node", function (evt) {
        var node = evt.target;
        let name = node._private.data.name;
        let nodePrivate = node._private;
        var event = event || window.event;
        let data = nodePrivate.data;

        me.Node = {
          id: node.id(),
          name: name,
          x: nodePrivate.bodyBounds.x1,
          y: nodePrivate.bodyBounds.y1,
          position: nodePrivate.position,
          pan: nodePrivate.cy._private.pan,
        };
        let box = $("#box");
        let boxH = box.position().top;
        $("#info").prop("style", function (i, val) {
          if (i >= 0) {
            let num = 58;
            if (node.id() == "start" || node.id() == "finish") {
              //补充差值
              num = 30;
            }
            let h = $("#info").height();
            let x =
              nodePrivate.position.x +
              nodePrivate.cy._private.pan.x +
              nodePrivate.bodyBounds.w / 2;
            let y =
              nodePrivate.position.y + nodePrivate.cy._private.pan.y - num - h;

            val.top = y + "px";
            val.left = x + "px";
          }
        });
        if (!me.menuFlag) {
          me.infoFlag = true;
        }
      });
      //监听鼠标移出节点事件
      cy.on("mouseout", "node", function (evt) {
        me.infoFlag = false;
        me.Node = {};
      });
      // 监听连线的点击事件
      cy.on("tap", "edge", function (evt) {
        var edge = evt.target;

        let label = edge._private.data.label;
        // me.rlbFlag = true;
        if (label) {
          me.$notify.info({
            title: "消息",
            message: "edge is " + label,
          });
        }
      });
      /* cy.on('mousedown', 'layout', function(evt) {
				var node = evt.target;
				console.log('tapped layout', node);
			}); */
      cy.on("box", "layout", function (evt) {
        var node = evt.target;
        console.log("tapped layout box", node);
      });

      /* cy.ready(
				
			); // 图表准备就绪后立即运行
 */

      cy.ready(function (event) {
        $("canvas").map(function (i, eve) {
          let styleObj = $(this).attr("style");
          $(this).attr("style", styleObj + " top:0;left:0");
        });
        //设置指定背景图
        let finish = cy.getElementById("finish");
        finish.style("background-image", [
          "https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/6460969261/p309801.png",
        ]);

        setTimeout(() => {
          //设置步骤类型
          // 同步风格:
          cy.batch(function () {
            nodes.map((item) => {
              let id = item.data.id;

              let typeClass = $("span[data-type=" + id + "]");

              if (id != "start" && id != "finish") {
                typeClass.show();
              }

              let nodeObj = cy.getElementById(id);

              let height = nodeObj._private.bodyBounds.h;
              console.log("nodeObj", nodeObj);
              let position = nodeObj._private.position;
              console.log("position", position);
              let x = position.x;
              let y = position.y;
              let w = typeClass.outerWidth();
              $("span[data-type=" + id + "]").prop("style", function (i, val) {
                val.top = y + height / 2 + "px";
                val.left = x - w / 2 + "px";
              });
            });
          });
        }, 1400);
      });
      /* cy.on('mousedown', e => {
				console.log('mousedown else', e.target.id);
				if(e.target.id==undefined){
					console.log('mousedown undefined');
					cy.resize()
				}
				return false;
			}); */
      cy.on("drag", (e) => {
        me.downFlag = false;
        console.log("drag else", e);
      });
      cy.on("tap", (e) => {
        //点击空白处
        var obj = e.target;

        if (!obj.isNode && !obj.isEdge) {
          me.rlbFlag = false;
          me.menuFlag = false;
          cy.nodes().classes([]); // 清空所有样式
          if (me.innerFlag) {
            cy.nodes().addClass("w");
          }
        }
      });
      cy.on("mousedown", (e) => {
        var obj = e.target;
        if (!obj.isNode && !obj.isEdge) {
          me.downFlag = true;
          console.log("me.downFlag", me.downFlag);
          me.menuFlag = false;
        }
      });
      cy.on("mouseup", (e) => {
        me.downFlag = false;
        console.log("me.downFlag", me.downFlag);
      });

      cy.on("mousemove", (e) => {
        if (me.downFlag) {
          console.log("move move move move");
        }
      });

      cy.on("boxstart", (en) => {
        console.log("me.boxstart ");
      });
      $("#inner").on("click", function () {
        me.innerFlag = true;
        // 同步风格:
        cy.batch(function () {
          nodes.map((item) => {
            let id = item.data.id;
            let h = $("span[data-id=" + id + "]").outerHeight();
            let w = $("span[data-id=" + id + "]").outerWidth();
            cy.$("#" + id).style("width", w);
            cy.$("#" + id).style("height", h);
            cy.$("#" + id).addClass("w");
          });
          let finish = cy.getElementById("finish");
          finish.style("background-image", []);
          let imgW =
            finish._private.rscratch.labelX +
            finish._private.rscratch.labelWidth +
            cy._private.pan.x +
            10;
          let imgh = finish._private.rscratch.labelY + cy._private.pan.y + 8;
          $("#innerSrc").prop("style", function (i, val) {
            val.top = imgh + "px";
            val.left = imgW + "px";
          });
        });
      });
    },
  },
};
</script>

<style scoped="scoped">
#all {
  width: 100%;
  height: 100%;
  background-color: #fff;
}
.mgL20 {
  margin-left: 20px;
}
.mgL10 {
  margin-left: 10px;
}
.mgL30 {
  margin-left: 30px;
}
.flex {
  display: flex;
  align-items: center;
}
#nodeHead {
  display: flex;
  padding: 0 10px;
}

#box {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #fff;
  margin: 6px;
  border: 1px solid;
}
#cy {
  width: 100%;
  height: 100%;
  background-color: #fff;
}
canvas {
  position: absolute;
  left: 0;
  top: 0;
  background-color: #fff;
}
#rlb {
  width: 320px;
  height: 200px;
  border: 1px solid #000066;
  border-radius: 8px;

  color: #888;
  background: #dbefff;
  padding: 16px 26px;
  position: fixed;
  bottom: 40px;
  right: 40px;
  z-index: 6;
  text-align: left;
}
#d1 {
  color: #fff;
  background-image: linear-gradient(-45deg, #551eed, #8a6be0);
  height: 30px;
  line-height: 30px;
  font-size: 16px;
  font-weight: bold;
  border-bottom: 1px solid #e7e7e7;
  margin-bottom: 6px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
#d2 {
  margin-bottom: 14px;
}
#info {
  position: absolute;
  width: 260px;
  padding: 10px;
  background: #dbefff;
  padding: 0 6px;
  text-align: left;
  border: 1px solid #999;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 7;
}
#info div {
  min-height: 30px;
  line-height: 30px;
  display: flex;
  justify-content: space-between;
}
#info div:not(:last-child) {
  /* border-bottom: 1px solid #999; */
}
.title {
  font-weight: bold;
}
.nodeInfoTitle {
  width: 80px;
}
.nodeInfoText {
  width: calc(100% - 80px);
  word-wrap: break-word;
  word-break: normal;
}
#menu {
  position: absolute;
  width: 220px;
  background-color: #fff;
  padding: 2px 0px;
  z-index: 5;
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
#menu div {
  padding: 0 30px;
  text-align: left;
  height: 26px;
  line-height: 26px;
  font-size: 14px;
  cursor: pointer;
}
#menu div:hover {
  background-color: #e1e1e1;
}
.idDiv {
  display: inline-block;
  max-width: 220px;
  min-width: 100px;
  min-height: 42px;
  word-wrap: break-word;
  word-break: normal;
  padding: 4px 10px;
}
#innerSrc {
  position: absolute;
  width: 20px;
  height: 20px;
  z-index: 6;
}
.typeDiv {
  position: absolute;
  display: inline-block;
  max-width: 180px;
  min-width: 50px;
  min-height: 22px;
  word-wrap: break-word;
  word-break: normal;
  padding: 4px 10px;
  z-index: 6;
  border-radius: 8px;
  background-color: #79c5f2;
  color: #fff;
  font-size: 14px;
}
</style>
